package com.banmao.snake_client.netty.client;

import com.banmao.snake_client.netty.handler.LoginResponseHandler;
import com.banmao.snake_core.entity.GlobalConstant;
import com.banmao.snake_core.netty.message.impl.LoginRequestMessage;
import com.banmao.snake_core.netty.protocol.MessageCodecSharable;
import com.banmao.snake_core.netty.protocol.ProcotolFrameDecoder;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.logging.LoggingHandler;
import lombok.extern.slf4j.Slf4j;

import java.net.InetSocketAddress;

// 客户端
@Slf4j
public class ClientService {

    private static volatile Channel channel = null;
    private static final Object LOCK = new Object();

    public static Channel getChannel() {
        if (channel == null) {
            synchronized (LOCK) {
                if(channel == null) {
                    openClient();
                }
            }
        }
        return channel;
    }

    private static void openClient() {

        try {
            NioEventLoopGroup eventLoopGroup = new NioEventLoopGroup();
            channel = new Bootstrap()
                    .group(eventLoopGroup)
                    .channel(NioSocketChannel.class)
                    .handler(new ChannelInitializer<NioSocketChannel>() {
                        @Override
                        protected void initChannel(NioSocketChannel ch) throws Exception {
                            ChannelPipeline pipeline = ch.pipeline();
                            pipeline.addLast(new ProcotolFrameDecoder());
                            pipeline.addLast(new LoggingHandler());
                            pipeline.addLast(new MessageCodecSharable());
                            pipeline.addLast(new LoginResponseHandler());
                            pipeline.addLast(new ChannelInboundHandlerAdapter() {
                                @Override
                                public void channelActive(ChannelHandlerContext ctx) throws Exception {
                                    log.info("连接成功... address: {}, port: {}", GlobalConstant.ADDRESS, GlobalConstant.PORT);
                                }
                            });
                        }
                    })
                    .connect(new InetSocketAddress(GlobalConstant.ADDRESS, GlobalConstant.PORT))
                    .sync().channel();

            channel.closeFuture().addListener(future -> {
                log.info("client channel closing...");
                eventLoopGroup.shutdownGracefully();
                channel = null;
            });

        } catch (Exception e) {
            log.error("ClientService msg:{} :", e.getMessage(), e);
            channel.close();
            throw new RuntimeException(e);
        }

    }

    public static void close() {
        if(channel != null) {
            channel.close();
        }
    }

    public static void main(String[] args) {
        openClient();

        LoginRequestMessage request = new LoginRequestMessage();
        request.setUsername("张三");
        request.setPassword("123123");

        channel.writeAndFlush(request);
    }

}
